<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:fo="http://www.w3.org/1999/XSL/Format" 
	xmlns:hbm="urn:nhibernate-mapping-2.2"
	xmlns:ms="urn:schemas-microsoft-com:xslt"
	xmlns:user="urn:xslt-helper"
	xmlns:helper="urn:helper">
	<xsl:import href="property.xslt"/>
	<xsl:output method="text" encoding="UTF-8"/>

	<xsl:template match="hbm:class">
		<xsl:param name="dto"/>		
		<xsl:variable name="name" select="@name"/>
		<xsl:if test="$dto!='true' and $use-dto='true'">
			<xsl:call-template name="GenerateInterface">
				<xsl:with-param name="class" select="@name"/>
			</xsl:call-template>
		</xsl:if>
		<xsl:call-template name="GenerateClass">
			<xsl:with-param name="class" select="$name"/>
			<xsl:with-param name="dto" select="$dto"/>
		</xsl:call-template>
		<xsl:for-each select="hbm:subclass">
			<xsl:if test="$dto!='true' and $use-dto='true'">
				<xsl:call-template name="GenerateInterface">
					<xsl:with-param name="class" select="@name"/>
					<xsl:with-param name="base-class" select="$name"/>
				</xsl:call-template>
			</xsl:if>
			<xsl:call-template name="GenerateClass">
				<xsl:with-param name="class" select="@name"/>
				<xsl:with-param name="base-class" select="$name"/>
				<xsl:with-param name="dto" select="$dto"/>
			</xsl:call-template>
		</xsl:for-each>
		<xsl:for-each select=".//hbm:component[string(./hbm:meta[@attribute='generate'])!='false']">
			<xsl:if test="$dto!='true' and $use-dto='true'">
				<xsl:call-template name="GenerateInterface">
					<xsl:with-param name="class" select="@class"/>
				</xsl:call-template>
			</xsl:if>
			<xsl:call-template name="GenerateClass">
				<xsl:with-param name="dto" select="$dto"/>
			</xsl:call-template>
		</xsl:for-each>
	</xsl:template>

	<xsl:template name="GenerateInterface">
		<xsl:param name="class"/>
		<xsl:param name="base-class"/>
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="concat(hbm:meta[@attribute='comment'], hbm:comment)"/>
			<xsl:with-param name="level" select="1"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab, 'public interface I', $class)"/>
		<xsl:if test="$base-class!=''">
			<xsl:value-of select="concat(' : I', $base-class)"/>
		</xsl:if>
	{
		<xsl:variable name="prop-list">
			<xsl:call-template name="PropertyList">
				<xsl:with-param name="purpose">interface</xsl:with-param>
			</xsl:call-template>
		</xsl:variable>		
		<xsl:for-each select="ms:node-set($prop-list)/property">
			<xsl:call-template name="PropertyInterfaceDeclaration"/>
		</xsl:for-each>
	}
	</xsl:template>
	
	<xsl:template name="GenerateClass">
		<xsl:param name="base-class"/>
		<xsl:param name="class" select="@class"/>
		<xsl:param name="dto">false</xsl:param>
		<xsl:param name="comment" select="concat(hbm:meta[@attribute='comment'], hbm:comment)"/>
		<xsl:variable name="dto-suffix">
			<xsl:if test="$dto='true'">Dto</xsl:if>
		</xsl:variable>
		<xsl:variable name="not-dto-suffix">
			<xsl:if test="$dto!='true'">Dto</xsl:if>
		</xsl:variable>
		<xsl:variable name="free-text" select="count(hbm:meta[@attribute='free-text'])>0"/>
		<xsl:variable name="name" select="concat($class, $dto-suffix)"/>
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="$comment"/>
			<xsl:with-param name="level" select="1"/>
		</xsl:call-template>
		<xsl:if test="$free-text">
			<xsl:value-of select="concat($newline, $tab)"/>
			<xsl:value-of select="concat('[NHibernate.Search.Attributes.Indexed(', string(hbm:meta[@attribute='free-text']), ')]')"/>
		</xsl:if>
	[Serializable]
	public partial class <xsl:value-of select="concat($name, ' : ')"/>
		<xsl:if test="string-length($base-class)>0">
			<xsl:value-of select="concat($base-class, $dto-suffix, ', ')"/>
		</xsl:if>ICloneable<xsl:if test="$use-dto='true'">
			, I<xsl:value-of select="$class"/>
		</xsl:if>
	{
		#region Конструкторы
		<xsl:call-template name="DefaultConstructor">
			<xsl:with-param name="name" select="$name"/>
			<xsl:with-param name="dto" select="$dto"/>
		</xsl:call-template>
		
		<!--<xsl:if test="$dto!='true' and name()!='component'">
			<xsl:variable name="prop-list"
				select="*[name()='property' or name()='one-to-one' or name()='many-to-one'][string(@insert)!='false' and count(@formula)=0]"/>
			<xsl:variable name="base-prop-list" 
				select="(../*)[name()='property' or name()='one-to-one' or name()='many-to-one'][string(@insert)!='false' and count(@formula)=0]"/>
			<xsl:if test="count($prop-list|$base-prop-list)>0">
				<xsl:call-template name="GenerateConstructor">
					<xsl:with-param name="name" select="$name"/>
					<xsl:with-param name="prop-list" select="$prop-list"/>
					<xsl:with-param name="base-prop-list" select="$base-prop-list"/>
				</xsl:call-template>
			</xsl:if>
			<xsl:if test="count($prop-list|$base-prop-list)!=count(($prop-list|$base-prop-list)[@not-null!='false'])">
				<xsl:call-template name="GenerateConstructor">
					<xsl:with-param name="name" select="$name"/>
					<xsl:with-param name="prop-list" select="$prop-list[@not-null!='false']"/>
					<xsl:with-param name="base-prop-list" select="$base-prop-list[@not-null!='false']"/>
				</xsl:call-template>
			</xsl:if>
		</xsl:if>-->
		#endregion

		<xsl:if test="$use-dto='true'">
		#region I<xsl:value-of select="$class"/>

		<xsl:variable name="interface-prop-list">
			<xsl:call-template name="PropertyList">
				<xsl:with-param name="purpose">interface</xsl:with-param>
			</xsl:call-template>
		</xsl:variable>
		<xsl:for-each select="ms:node-set($interface-prop-list)/property">
			<xsl:call-template name="PropertyInterfaceImplementation">
				<xsl:with-param name="class-name" select="$class"/>
			</xsl:call-template>
		</xsl:for-each>

		#endregion
		</xsl:if>

		#region Копирование
		<xsl:variable name="anti-class" select="concat($class, $not-dto-suffix)"/>

		<xsl:if test="$use-dto='true'">
			<xsl:call-template name="CopyTo_Method">
				<xsl:with-param name="dto" select="$dto"/>
				<xsl:with-param name="base-class" select="$base-class"/>
				<xsl:with-param name="class" select="$class"/>
				<xsl:with-param name="purpose">dto</xsl:with-param>
			</xsl:call-template>
		</xsl:if>

		<xsl:call-template name="CopyTo_Method">
			<xsl:with-param name="dto" select="$dto"/>
			<xsl:with-param name="base-class" select="$base-class"/>
			<xsl:with-param name="class" select="$class"/>
			<xsl:with-param name="purpose">clone</xsl:with-param>
		</xsl:call-template>

		<xsl:if test="$dto!='true' and $use-dto='true'">
		///&lt;summary&gt;
		/// создает список Dto по списку объектов бизнес модели. Вместо этого метода настоятельно
		/// рекомендуется пользоваться перегруженной версией, принимающей Hashtable для маппинга
		/// DomainObject -> Dto, чтобы избежать проблем на клиенте связанных с тем, что есть 2
		/// разных объекта Dto для одного объекта модели. Особенно актуально если в методе фасада
		/// есть несколько вызовов CreateDtoObject или CreateDtoObjectList
		///&lt;/summary&gt;			
		public static List&lt;<xsl:value-of select="$name"/>Dto&gt; CreateDtoObjectList(IEnumerable&lt;<xsl:value-of select="$name"/>&gt; enumerable, int? level)
		{
			Hashtable domainObject2Dto = new Hashtable();
			return CreateDtoObjectList(enumerable, level, ref domainObject2Dto);
		}

		///&lt;summary&gt;
		/// создает список Dto по списку объектов бизнес модели.
		///&lt;/summary&gt;
		public static List&lt;<xsl:value-of select="$name"/>Dto&gt; CreateDtoObjectList(IEnumerable&lt;<xsl:value-of select="$name"/>&gt; enumerable, int? level, ref Hashtable domainObject2Dto)
		{
			if (enumerable == null)
				return null;
			List&lt;<xsl:value-of select="$name"/>Dto&gt; res = new List&lt;<xsl:value-of select="$name"/>Dto&gt;();
			foreach (<xsl:value-of select="$name"/> obj in enumerable)
				res.Add((<xsl:value-of select="$name"/>Dto)obj.CreateDtoObject(level, domainObject2Dto));
			return res;
		}

		</xsl:if>
		
		#endregion		
		<xsl:text>
		#region Properties
		</xsl:text>
		<xsl:variable name="prop-list">
			<xsl:call-template name="PropertyList">
				<xsl:with-param name="purpose">
					<xsl:choose>
						<xsl:when test="$dto='true'">dto</xsl:when>
						<xsl:otherwise>class</xsl:otherwise>
					</xsl:choose>
				</xsl:with-param>
			</xsl:call-template>
		</xsl:variable>
		<xsl:for-each select="ms:node-set($prop-list)/property">
			<xsl:call-template name="PropertyImplementation">
				<xsl:with-param name="dto" select="$dto"/>
				<xsl:with-param name="free-text" select="$free-text"/>
			</xsl:call-template>
		</xsl:for-each>		
	
		<xsl:text>		
		#endregion
	}
		</xsl:text>
	</xsl:template>

	<xsl:template name="PropertyImplementation">
		<xsl:param name="dto">false</xsl:param>
		<xsl:param name="free-text"/>
		<xsl:if test="$dto!='true'">
			<xsl:call-template name="comment">
				<xsl:with-param name="text" select="@comment"/>
			</xsl:call-template>
			<xsl:value-of select="concat($newline, $tab2, 'public const string ', @name, 'Prop = &quot;', @name, '&quot;;')"/>
		</xsl:if>		
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="@comment"/>
		</xsl:call-template>
		<xsl:if test="$free-text and hbm:id and $dto!='true'">
			<xsl:value-of select="concat($newline, $tab2, '[NHibernate.Search.Attributes.DocumentId]')"/>
		</xsl:if>
		<xsl:if test="$dto!='true' and $free-text and hbm:*[1]/hbm:meta[@attribute='free-text']">
			<xsl:value-of select="concat($newline, $tab2)"/>
			<xsl:variable name="free-text-param" select="string(hbm:*[1]/hbm:meta[@attribute='free-text'])"/>
			<xsl:choose>
				<xsl:when test="$free-text-param=''">[NHibernate.Search.Attributes.Field(NHibernate.Search.Attributes.Index.Tokenized)]</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="concat('[NHibernate.Search.Attributes.Field(', $free-text-param, ')]')"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
		<xsl:if test="hbm:*[1]/hbm:meta[@attribute='xml-ignore']">
			<xsl:value-of select="concat($newline, $tab2, '[System.Xml.Serialization.XmlIgnore]')"/>
		</xsl:if>
		<xsl:value-of select="concat($newline, $tab2)"/>
		<xsl:value-of select="concat('public virtual ', @type, ' ', @name)"/>
		<xsl:value-of select="concat($newline, $tab2, '{')"/>
		<xsl:value-of select="concat($newline, $tab3, 'get; set;')"/>
		<xsl:value-of select="concat($newline, $tab2, '}')"/>
	</xsl:template>

	<xsl:template name="PropertyInterfaceDeclaration">
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="@comment"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab2, @type, ' ', @name, ' { get; }')"/>
	</xsl:template>

	<xsl:template name="PropertyInterfaceImplementation">
		<xsl:param name="class-name"/>
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="@comment"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab2, @type, ' I', $class-name, '.', @name)"/>
		<xsl:value-of select="concat($newline, $tab2, '{', $newline, $tab3, 'get { return this.', @name)"/>
		<xsl:if test="@prop-type='collection' and @index-type=''">
			<xsl:value-of select="concat(' == null ? null : ', @name)"/>
			<xsl:value-of select="concat('.OfType&lt;', @item-type, '&gt;()')"/>
		</xsl:if>
		<xsl:if test="@prop-type='collection' and @index-type!=''">
			<xsl:if test="@item-prop-type='entity' or @index-prop-type='entity'">
				<xsl:variable name="index-prefix">
					<xsl:if test="@index-prop-type='entity'">
						<xsl:value-of select="concat('(', @index-type, ')')"/>
					</xsl:if>
				</xsl:variable>
				<xsl:variable name="item-prefix">
					<xsl:if test="@item-prop-type='entity'">
						<xsl:value-of select="concat('(', @item-type, ')')"/>
					</xsl:if>
				</xsl:variable>
				<xsl:value-of select="concat('.ToDictionary(item =&gt; ', $index-prefix,'item.Key, item =&gt; ', $item-prefix, 'item.Value)')"/>
			</xsl:if>
		</xsl:if>
		<xsl:value-of select="concat('; }', $newline, $tab2, '}', $newline)"/>
	</xsl:template>

	<xsl:template name="CopyTo_Method">
		<xsl:param name="class" select="@name"/>
		<xsl:param name="base-class"/>
		<xsl:param name="dto">false</xsl:param>
		<xsl:param name="purpose">dto</xsl:param>
		
		<xsl:variable name="dto-suffix">
			<xsl:if test="$dto='true'">Dto</xsl:if>
		</xsl:variable>
		<xsl:variable name="not-dto-suffix">
			<xsl:if test="$dto-suffix=''">Dto</xsl:if>
		</xsl:variable>
		<xsl:variable name="sourceClass" select="concat($class, $dto-suffix)"/>
		<xsl:variable name="resultClass">
			<xsl:choose>
				<xsl:when test="$purpose='dto'">
					<xsl:value-of select="concat($class, $not-dto-suffix)"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$sourceClass"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="returnClass">
			<xsl:choose>
				<xsl:when test="$base-class!='' and $purpose='dto'">
					<xsl:value-of select="concat($base-class, $not-dto-suffix)"/>
				</xsl:when>
				<xsl:when test="$base-class!='' and $purpose='clone'">
					<xsl:value-of select="concat($base-class, $dto-suffix)"/>
				</xsl:when>
				<xsl:when test="$base-class=''">
					<xsl:value-of select="$resultClass"/>
				</xsl:when>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="virtual">
			<xsl:choose>
				<xsl:when test="$base-class!=''">override</xsl:when>
				<xsl:otherwise>virtual</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="level">
			<xsl:if test="$dto-suffix=''">level, </xsl:if>
		</xsl:variable>
		<xsl:variable name="level-decl">
			<xsl:if test="$dto-suffix=''"> int? level,</xsl:if>
		</xsl:variable>
		<xsl:variable name="CheckNeedCopyDecl">
			<xsl:value-of select="string('CheckNeedCopy')"/>
			<xsl:if test="$purpose='dto'">Dto</xsl:if>
		</xsl:variable>
		<xsl:variable name="CheckNeedCopy" select="concat('.', $CheckNeedCopyDecl, '(', $level, 'list)')"/>
		<xsl:variable name="CopyToName">
			<xsl:choose>
				<xsl:when test="$purpose='dto'">CopyTo</xsl:when>
				<xsl:otherwise>CloneTo</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="create-method" select="concat('Create', $not-dto-suffix, 'Object')"/>
		<xsl:variable name="create-object-signature">
			<xsl:choose>
				<xsl:when test="$base-class!=''">public override </xsl:when>
				<xsl:otherwise>public virtual </xsl:otherwise>
			</xsl:choose>
			<xsl:value-of select="concat($returnClass, ' ', $create-method)"/>
		</xsl:variable>
		<xsl:variable name="prop-list">
			<xsl:call-template name="PropertyList">
				<xsl:with-param name="purpose">
					<xsl:choose>
						<xsl:when test="$dto='true' or $purpose='dto'">dto</xsl:when>
						<xsl:otherwise>class</xsl:otherwise>
					</xsl:choose>
				</xsl:with-param>
				<xsl:with-param name="type-purpose">
					<xsl:choose>
						<xsl:when test="$purpose='clone' and $dto='true'">dto</xsl:when>
						<xsl:when test="$purpose='clone' and $dto!='true'">class</xsl:when>
						<xsl:when test="$purpose='dto' and $dto!='true'">dto</xsl:when>
						<xsl:when test="$purpose='dto' and $dto='true'">class</xsl:when>
					</xsl:choose>
				</xsl:with-param>
			</xsl:call-template>
		</xsl:variable>

		<xsl:if test="$purpose='dto'">
			<!-- CreateObject - вспомогательный метод -->
			<xsl:call-template name="comment">
				<xsl:with-param name="text">Создать парный DTO объект</xsl:with-param>
			</xsl:call-template>
			<xsl:if test="$level!=''">
				<xsl:value-of select="concat($newline, $tab2, '/// &lt;param name=&quot;level&quot;&gt;', 'уровень глубины копии', '&lt;/param&gt;')"/>
			</xsl:if>
			<xsl:value-of select="concat($newline, $tab2, '/// &lt;param name=&quot;list&quot;&gt;', 'хеш копируемых объектов', '&lt;/param&gt;')"/>
			<xsl:value-of select="concat($newline, $tab2, '/// &lt;returns&gt;', 'парный объект', '&lt;/returns&gt;')"/>

			<xsl:value-of select="concat($newline, $tab2, $create-object-signature, '(', normalize-space($level-decl), ' Hashtable list)')"/>
			<xsl:value-of select="concat($newline, $tab2, '{')"/>
			<xsl:value-of select="concat($newline, $tab3, 'var result = new ', $resultClass, '();')"/>
			<xsl:value-of select="concat($newline, $tab3, 'this.', $CopyToName, '(result, ', $level, 'list);')"/>
			<xsl:value-of select="concat($newline, $tab3, 'return result;')"/>
			<xsl:value-of select="concat($newline, $tab2, '}', $newline)"/>

			<xsl:call-template name="comment">
				<xsl:with-param name="text">Создать парный DTO объект</xsl:with-param>
			</xsl:call-template>
			<xsl:if test="$level!=''">
				<xsl:value-of select="concat($newline, $tab2, '/// &lt;param name=&quot;level&quot;&gt;', 'уровень глубины копии', '&lt;/param&gt;')"/>
			</xsl:if>
			<xsl:value-of select="concat($newline, $tab2, '/// &lt;returns&gt;', 'парный объект', '&lt;/returns&gt;')"/>

			<xsl:value-of select="concat($newline, $tab2, $create-object-signature, '(')"/>
			<xsl:if test="$level!=''">int? level</xsl:if>
			<xsl:value-of select="string(')')"/>
			<xsl:value-of select="concat($newline, $tab2, '{')"/>
			<xsl:value-of select="concat($newline, $tab3, 'return ', $create-method, '(', $level, 'null);')"/>
			<xsl:value-of select="concat($newline, $tab2, '}', $newline)"/>
		</xsl:if>
		<xsl:if test="$purpose='clone'">
			<!-- Clone - глубокое копирование -->
			<xsl:value-of select="concat($newline, $tab2, 'object ICloneable.Clone() { return this.Clone(); }', $newline)"/>

			<xsl:call-template name="comment">
				<xsl:with-param name="text">Клонировать объект - глубокое копирование</xsl:with-param>
			</xsl:call-template>
			<xsl:value-of select="concat($newline, $tab2, '/// &lt;returns&gt;', 'Клонированный объект', '&lt;/returns&gt;')"/>
			<xsl:value-of select="concat($newline, $tab2, 'public ')"/>
			<xsl:variable name="baseClass" select="concat($base-class, $dto-suffix)"/>
			<xsl:choose >
				<xsl:when test="$base-class!=''">override <xsl:value-of select="concat($baseClass, ' Clone()')"/></xsl:when>
				<xsl:otherwise>virtual <xsl:value-of select="concat($sourceClass, ' Clone()')"/></xsl:otherwise>
			</xsl:choose>
			<xsl:value-of select="concat($newline, $tab2, '{')"/>
			<xsl:value-of select="concat($newline, $tab3, 'var result = new ', $sourceClass, '();')"/>
			<xsl:value-of select="concat($newline, $tab3, 'this.', $CopyToName, '(result, ')"/>
			<xsl:if test="$level!=''">null, </xsl:if>
			<xsl:value-of select="string('null);')"/>
			<xsl:choose >
				<xsl:when test="$base-class!=''">
					<xsl:value-of select="concat($newline, $tab3, 'return result', ' as ',$baseClass, ';')"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="concat($newline, $tab3, 'return result;')"/>
				</xsl:otherwise>
			</xsl:choose>
			
			<xsl:value-of select="concat($newline, $tab2, '}', $newline)"/>
		</xsl:if>

		<!-- CheckNeedCopy - вспомогательный метод -->
		<xsl:call-template name="comment">
			<xsl:with-param name="text">CheckNeedCopy - вспомогательный метод</xsl:with-param>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab2, '/// &lt;returns&gt;', '', '&lt;/returns&gt;')"/>
		<xsl:value-of select="concat($newline, $tab2, 'public ')"/>
		<xsl:value-of select="concat($virtual, ' ', $returnClass, ' ', $CheckNeedCopyDecl, '(', normalize-space($level-decl), ' Hashtable list)')"/>
		<xsl:value-of select="concat($newline, $tab2, '{')"/>
		<xsl:if test="$level!=''">
			<xsl:value-of select="concat($newline, $tab3, 'if (!(level == null || level > 0))')"/>
			<xsl:value-of select="concat($newline, $tab2, $tab2, 'return null;')"/>
		</xsl:if>

		<xsl:value-of select="concat($newline, $tab3, 'if (list.Contains(this))')"/>
		<xsl:value-of select="concat($newline, $tab2, $tab2, 'return (', $resultClass, ')list[this];')"/>
		<xsl:value-of select="concat($newline, $tab3, 'var result = new ', $resultClass, '();')"/>
		<xsl:value-of select="concat($newline, $tab3, 'list.Add(this, result);')"/>
		<xsl:value-of select="concat($newline, $tab3, 'this.', $CopyToName, '(result, ')"/>
		<xsl:if test="$level!=''">level - 1, </xsl:if>
		<xsl:value-of select="string('list);')"/>
		<xsl:value-of select="concat($newline, $tab3, 'return result;')"/>
		<xsl:value-of select="concat($newline, $tab2, '}', $newline)"/>

		<!-- CopyTo - декларация метода копирования -->
		<xsl:call-template name="comment">
			<xsl:with-param name="text">Клонировать объект - глубоко скопировать текущий объект в выбранный</xsl:with-param>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab2, '/// &lt;param name=&quot;target&quot;&gt;', 'куда копируем', '&lt;/param&gt;')"/>
		<xsl:if test="$level!=''">
			<xsl:value-of select="concat($newline, $tab2, '/// &lt;param name=&quot;level&quot;&gt;', 'уровень глубины копии', '&lt;/param&gt;')"/>
		</xsl:if>
		<xsl:value-of select="concat($newline, $tab2, '/// &lt;param name=&quot;list&quot;&gt;', 'хеш копируемых объектов', '&lt;/param&gt;')"/>

		<xsl:value-of select="concat($newline, $tab2, 'public ', $virtual, ' void ', $CopyToName, '(', $returnClass, ' target,', $level-decl, ' Hashtable list)')"/>
		<xsl:value-of select="concat($newline, $tab2, '{')"/>
		<xsl:value-of select="concat($newline, $tab3, 'if (list == null)', $newline, $tab2, $tab2, 'list = new Hashtable();')"/>
		<xsl:if test="$base-class!=''">
			<!-- вызов базового класса -->
			<xsl:value-of select="concat($newline, $tab3, 'base.', $CopyToName, '(target,', $level, ' list);')"/>
		</xsl:if>
		<!-- проверка соответсвия типа -->
		<xsl:value-of select="concat($newline, $tab3, 'var result = target as ', $resultClass, ';')"/>
		<xsl:value-of select="concat($newline, $tab3, 'if (result == null)', $newline, $tab3, $tab, 'return;')"/>
		
		<!-- копирование скалярных значений -->
		<xsl:for-each select="ms:node-set($prop-list)/property[@prop-type='value']">
			<xsl:value-of select="concat($newline, $tab3, 'result.', @name, ' = this.', @name, ';')"/>
		</xsl:for-each>
		<!-- копирование ссылок -->
		<xsl:for-each select="ms:node-set($prop-list)/property[@prop-type='entity']">
			<xsl:value-of select="concat($newline, $tab3, 'result.', @name, ' = this.', @name, ' == null ? null : (', @type,')this.', @name, $CheckNeedCopy, ';')"/>
		</xsl:for-each>
		
		<!-- копирование коллекций -->
		<xsl:if test="$level!='' and count(ms:node-set($prop-list)/property[@prop-type='collection'])>0">
			<xsl:value-of select="concat($newline, $tab3, 'if (!(level == null || level > 1))')"/>
			<xsl:value-of select="concat($newline, $tab2, $tab2, 'return;')"/>
		</xsl:if>
		<xsl:for-each select="ms:node-set($prop-list)/property[@prop-type='collection']">
			<xsl:choose>
				<xsl:when test="@index-type!=''">
					<!-- обработка словарей -->
					<xsl:variable name="index-copy-code">
						<xsl:if test="@index-prop-type='entity'">
							<xsl:value-of select="$CheckNeedCopy"/>
						</xsl:if>
					</xsl:variable>
					<xsl:variable name="item-copy-code">
						<xsl:if test="@item-prop-type='entity'">
							<xsl:value-of select="$CheckNeedCopy"/>
						</xsl:if>
					</xsl:variable>
					<xsl:value-of select="concat($newline, $tab3, 'result.', @name, ' = this.', @name, ' == null ? null : this.', @name)"/>
					<xsl:value-of select="concat('.ToDictionary(item =&gt; item.Key', $index-copy-code,', item =&gt; item.Value', $item-copy-code,');')"/>
				</xsl:when>
				<xsl:when test="$dto!='true' and $purpose='dto'">
					<xsl:value-of select="concat($newline, $tab3, 'result.', @name, ' = this.', @name, ' == null ? null : this.', @name)"/>
					<xsl:if test="@item-prop-type='entity'">						
						<xsl:value-of select="concat('.Select(item => (', @item-type,')item', $CheckNeedCopy, ')')"/>
					</xsl:if>
					<xsl:value-of select="string('.ToArray();')"/>
				</xsl:when>
				<xsl:when test="($dto='true' and $purpose='dto') or $purpose='clone'">
					<xsl:variable name="collection" select="name(*[1])"/>
					<!-- реальный тип коллекции в не dto классе -->
					<xsl:variable name="instance-type">
						<xsl:call-template name="InstanceListType">
							<xsl:with-param name="type" select="@item-type"/>
							<xsl:with-param name="collection" select="$collection"/>
							<xsl:with-param name="dto" select="$purpose='clone' and $dto='true'"/>
						</xsl:call-template>
					</xsl:variable>
					
					<xsl:value-of select="concat($newline, $tab3, 'if (this.', @name, ' == null)')"/>
					<xsl:value-of select="concat($newline, $tab2, $tab2, 'result.', @name, ' = null;')"/>
					<xsl:value-of select="concat($newline, $tab3, 'else')"/>
					<xsl:value-of select="concat($newline, $tab2, $tab2, 'result.', @name, ' = ')"/>
					<xsl:variable name="source-enum-list">
						<xsl:choose>
							<xsl:when test="@item-prop-type='value'">
								<xsl:value-of select="concat('this.', @name)"/>
							</xsl:when>
							<xsl:otherwise>
								<xsl:value-of select="concat('this.', @name, '.Select(item => (',  @item-type,')item', $CheckNeedCopy, ')')"/>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:variable>
					<xsl:choose>
						<!-- массивы обрабытываем отдельно -->
						<xsl:when test="starts-with($instance-type, substring-before($instance-type, '[]')) and contains($instance-type, '[]')">
							<xsl:value-of select="concat($source-enum-list, '.ToArray();')"/>
						</xsl:when>
						<xsl:otherwise>
							<xsl:value-of select="concat('new ', $instance-type, '(', $source-enum-list, '.ToList());')"/>
						</xsl:otherwise>
					</xsl:choose>

				</xsl:when>
			</xsl:choose>
		</xsl:for-each>

		<xsl:value-of select="concat($newline, $tab2, '}', $newline)"/>
		
	</xsl:template>
	
	<xsl:template name="DefaultConstructor">
		<xsl:param name="dto"/>
		<xsl:param name="name" select="@name"/>
		<xsl:call-template name="comment">
			<xsl:with-param name="text">Конструктор по умолчанию</xsl:with-param>
		</xsl:call-template>
		public <xsl:value-of select="$name"/>() : base()<xsl:value-of select="concat($newline, $tab2, '{')"/>
		<xsl:if test="$dto!='true'">
			<xsl:variable name="list-props">
				<xsl:call-template name="PropertyList">
					<xsl:with-param name="purpose">class</xsl:with-param>
				</xsl:call-template>
			</xsl:variable>
			<xsl:for-each select="ms:node-set($list-props)/property[@prop-type='collection']">
				<xsl:variable name="list-type">
					<xsl:call-template name="InstanceListType">
						<xsl:with-param name="type" select="@item-type"/>
						<xsl:with-param name="index-type" select="@index-type"/>
						<xsl:with-param name="collection" select="name(*[1])"/>
					</xsl:call-template>
				</xsl:variable>
				<xsl:value-of select="concat($newline, $tab3, @name, ' = new ', $list-type, '();')"/>
			</xsl:for-each>
		</xsl:if>
		<xsl:value-of select="concat($newline, $tab2, '}', $newline)"/>
	</xsl:template>
	
	<xsl:template name="GenerateConstructor">
		<xsl:param name="name" select="@name"/>
		<xsl:param name="prop-list"/>
		<xsl:param name="base-prop-list"/>
		<xsl:call-template name="comment">
			<xsl:with-param name="text">Конструктор</xsl:with-param>
		</xsl:call-template>
		<xsl:for-each select="$base-prop-list|$prop-list">
			<xsl:value-of select="concat($newline, $tab2)"/>
			<xsl:value-of select="string('/// &lt;param name=&quot;')"/>
			<xsl:value-of select="helper:ToCamelCase(@name)"/>
			<xsl:value-of select="string('&quot;&gt;')"/>
			<xsl:value-of select="concat(hbm:meta[@attribute='comment'], hbm:comment)"/>
			<xsl:value-of select="string('&lt;/param&gt;')"/>
		</xsl:for-each>
		<xsl:value-of select="concat($newline, $tab2, 'public ', $name, '(')"/>
		<xsl:for-each select="$base-prop-list|$prop-list">
			<xsl:variable name="type">
				<xsl:choose>
					<xsl:when test="name(.)='property'">
						<xsl:call-template name="type2type">
							<xsl:with-param name="type" select="@type"/>
							<xsl:with-param name="not-null" select="@not-null"/>
						</xsl:call-template>
					</xsl:when>
					<xsl:otherwise>
						<xsl:call-template name="class2code">
							<xsl:with-param name="name" select="@class"/>
						</xsl:call-template>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:variable>
			<xsl:variable name="var" select="helper:ToCamelCase(@name)"/>
			<xsl:value-of select="concat($type, ' ', $var)"/>
			<xsl:if test="position()!=last()">, </xsl:if>
		</xsl:for-each>
		<xsl:value-of select="string(')')"/>
		<xsl:if test="count($base-prop-list)>0">
			<xsl:value-of select="string(': base(')"/>
			<xsl:for-each select="$base-prop-list">
				<xsl:value-of select="helper:ToCamelCase(@name)"/>
				<xsl:if test="position()!=last()">, </xsl:if>
			</xsl:for-each>
			<xsl:value-of select="string(')')"/>
		</xsl:if>
		{<xsl:for-each select="$prop-list">
			this.<xsl:value-of select="@name"/> = <xsl:value-of select="helper:ToCamelCase(@name)"/>;</xsl:for-each>
		}
	</xsl:template>
</xsl:stylesheet>
